#pragma once
#include <iostream>
#include <vector>
#include <functional>
#include <unordered_map>
#include <cstdint>
#include <cassert>
#include <string>
#include <cstring>
#include <memory>
#include <ctime>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <pthread.h>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <sys/eventfd.h>
#include <sys/timerfd.h>
#include <signal.h>


//技巧：加上do while循环能应用于代码的各种情况
//宏里面不能有换行，所以加上\转义换行，代表后面没有换行
#define INF 0
#define DBG 1
#define ERR 2
#define LOG_LEVEL ERR
#define LOG(level, format, ...)                                                                 \
    do                                                                                          \
    {                                                                                           \
    if (LOG_LEVEL > level)                                                                      \
        break;                                                                                  \
    time_t t = time(NULL);                                                                      \
    struct tm* lltime = localtime(&t);                                                          \
    char time[32];                                                                              \
    strftime(time, 31, "%H:%M:%S", lltime);                                                     \
    fprintf(stdout, "[%p %s %s:%d] " format "\n",(void*)pthread_self(), time, __FILE__, __LINE__, ##__VA_ARGS__);        \
    } while (0)
#define INF_LOG(format, ...) LOG(INF, format, ##__VA_ARGS__)// 使用不定参的...只能声明定义的时候用，使用的时候用__VA_ARGS__
#define DBG_LOG(format, ...) LOG(DBG, format, ##__VA_ARGS__)
#define ERR_LOG(format, ...) LOG(ERR, format, ##__VA_ARGS__)

#define BUFFER_DEFAULT_SIZE 1024
class Buffer
{
private:
    std::vector<char> _buffer;
    uint64_t _read_idx;     //相对读偏移量
    uint64_t _write_idx;    //相对写偏移量
public:
    Buffer()
    :_read_idx(0), _write_idx(0), _buffer(1024)
    {}
    //获取起始地址
    char* Begin() const
    {
        return (char*)&_buffer[0];
    }
    //获取当前写入起始地址
    char* WritePosition() const
    {
        return Begin() + _write_idx;
    }
    //获取当前读取起始地址
    char* ReadPosition() const
    {
        return Begin() + _read_idx;
    }
    //获取缓冲区末尾空闲空间大小 -- 写偏移之后的空闲空间
    uint64_t TailIdleSize() const
    {
        return _buffer.size() - _write_idx;
    }
    //获取缓冲区起始空闲空间大小 -- 读偏移之前的空闲空间
    uint64_t HeadIdleSize() const
    {
        return _read_idx;
    }
    //获取可读数据大小
    uint64_t ReadAbleSize() const
    {
        return _write_idx - _read_idx;
    }
    //将读偏移向后移动，必须小于可读数据大小
    void MoveReadOffset(uint64_t len)
    {
        assert(len <= ReadAbleSize());
        _read_idx += len;
    }
    //将写偏移向后移动，向后移动的大小必须小于前沿和后沿的空闲空间的大小
    void MoveWriteOffset(uint64_t len)
    {
        assert(len <= HeadIdleSize() + TailIdleSize());
        _write_idx += len;
    }
    //确保可写空间足够(整体空闲空间够了就移动数据，否则就扩容)
    void EnsureWriteSpace(uint64_t len)
    {
        if (TailIdleSize() > len)   //如果末尾空闲空间大小足够，直接返回
            return;
        //末尾空间不够，则判断加上起始空闲位置的空闲空间大小是否足够
        if (len <= TailIdleSize() + HeadIdleSize())
        {
            uint64_t rsz = ReadAbleSize();  //把当前数据大小先保存起来
            //copy：第一个参数，要拷贝的起始地址。第二个参数，要拷贝的末尾地址。第三个参数：拷贝到某个地址上面
            std::copy(ReadPosition(), ReadPosition() + rsz, Begin());
            _read_idx = 0;      //将读偏移归0
            _write_idx = rsz;   //将写偏移置为可读数据大小
        }
        else    //总体空间不够，扩容
        {
            _buffer.resize(_write_idx + len);
        }
    }
    //写入数据
    void Write(const void* data, uint64_t len)
    {
        //1。保证有足够空间 2。拷贝数据进去
        if (len == 0)   //防御性编程，不要嫌弃多次判断
            return;
        EnsureWriteSpace(len);
        std::copy((char*)data, (char*)data + len, WritePosition());
    }
    void WriteAndPush(const void* data, uint64_t len)
    {
        Write(data, len);
        MoveWriteOffset(len);
    }
    void WriteString(const std::string& data)
    {
        Write((const void*)data.c_str(), data.size());
    }
    void WriteStringAndPush(const std::string& data)
    {
        WriteString(data);
        MoveWriteOffset(data.size());
    }
    void WriteBuffer(Buffer& data)
    {
        Write((const void*)data.ReadPosition(), data.ReadAbleSize());
    } 
    void WriteBufferAndPush(Buffer& data)
    {
        WriteBuffer(data);
        MoveWriteOffset(data.ReadAbleSize());
    }
    //读取数据
    void Read(void* buf, uint64_t len)
    {
        //要求读取的数据大小必须小于可读数据的大小
        assert(len <= ReadAbleSize());
        std::copy(ReadPosition(), ReadPosition() + len, (char*)buf);
    }
    void ReadAndPop(void* buf, uint64_t len)
    {
        Read(buf, len);
        MoveReadOffset(len);
    }
    std::string ReadAsString(uint64_t len)
    {
        assert(len <= ReadAbleSize());
        std::string str;
        str.resize(len);
        Read(&str[0], len);
        return str;
    }
    std::string ReadAsStringAndPop(uint64_t len)
    {
        std::string str = ReadAsString(len);
        MoveReadOffset(len);
        return str;
    }
    char* FindCRLF()    //查找回车字符的地址
    {
        //查找某一个字节/字符
        char* res = (char*)memchr(ReadPosition(), '\n', ReadAbleSize());
        return res;
    }
    //获取一行数据
    std::string GetLine()
    {
        const char* pos = FindCRLF();
        if (pos == NULL)
            return "";
        return ReadAsString(pos - ReadPosition() + 1);  //包括将'\n'也读取进去 -- 方便后面对HTTP协议的操作
    }
    std::string GetLineAndPop()
    {
        std::string str = GetLine();
        MoveReadOffset(str.size());
        return str;
    }
    //清空缓冲区
    void Clear()
    {
        //只需要将偏移量归0即可
        _read_idx = 0;
        _write_idx = 0;
    }
};


#define MAX_LISTEN 1024
class Socket
{
private:
    int _sockfd;
public:
    Socket()
    :_sockfd(-1)
    {}
    Socket(int fd)
    :_sockfd(fd)
    {}
    ~Socket()
    {
        Close();
    }
    int Fd()
    {
        return _sockfd;
    }
    //创建套接字
    bool Create()
    {
        int ret = socket(AF_INET, SOCK_STREAM, 0);
        if (ret < 0)
        {
            ERR_LOG("CREATE SOCKET FAILED:%s", strerror(errno));
            return false;
        }
        _sockfd = ret;
        return true;
    }
    //绑定地址信息
    bool Bind(const std::string& ip, uint16_t port)
    {
        struct sockaddr_in addr;
        addr.sin_addr.s_addr = inet_addr(ip.c_str());
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        int ret = bind(_sockfd, (const sockaddr*)&addr, sizeof(addr));
        if (ret < 0)
        {
            ERR_LOG("BIND SOCKET FAILED:%s", strerror(errno));
            return false;
        }
        return true;
    }
    //开始监听
    bool Listen(int backlog = MAX_LISTEN)
    {
        int ret = listen(_sockfd, backlog);
        if (ret < 0)
        {
            ERR_LOG("LISTEN SOCKET FAILED:%s", strerror(errno));
            return false;
        }
        return true;
    }
    //向服务器发起连接
    bool Connect(const std::string& ip, uint16_t port)
    {
        struct sockaddr_in addr;
        addr.sin_addr.s_addr = inet_addr(ip.c_str());
        addr.sin_port = htons(port);
        addr.sin_family = AF_INET;
        int ret = connect(_sockfd, (const sockaddr*)&addr, sizeof(addr));
        if (ret < 0)
        {
            ERR_LOG("CONNECT SERVER FAILED:%s", strerror(errno));
            return false;
        }
        return true;

    }
    //获取新连接
    int Accept()
    {
        int newfd = accept(_sockfd, NULL, NULL);
        if (newfd < 0)
        {
            ERR_LOG("ACCEPT SOCKET FAILED:%s", strerror(errno));
            return -1;
        }
        return newfd;
    }
    //接收数据
    ssize_t Recv(void* Buffer, size_t len, int flag = 0)
    {
        int n = recv(_sockfd, Buffer, len, flag);
        if (n == 0)
        {
            //等于0的时候表示连接断开
            DBG_LOG("CONNECTION CLOSED");
            return -1;
        }
        if (n < 0)//小于0的时候表示读出错了
        {
            if (errno == EAGAIN || errno == EINTR)
            {
                //EAGAIN    表示当前socket的接收缓冲区中没有数据，在非阻塞情况下才会出现这种错误
                //EINTR     表示当前socket的阻塞等待被信号打断了
                return 0;   //表示这次没有接收到数据
            }
            ERR_LOG("SOCKET RECV FAILED");
            return -1;
        }
        return n;
    }
    //非阻塞读取
    ssize_t NonBlockRecv(void* buffer, size_t len)
    {
        return Recv(buffer, len, MSG_DONTWAIT);
    }
    //发送数据 -- 外部可以根据实际发送的数据长度来决定下一步的处理
    ssize_t Send(const void* buf, size_t len, int flag = 0)
    {
        int n = send(_sockfd, buf, len, flag);
        if (n < 0)
        {
            if (errno == EAGAIN || errno == EINTR)
            {
                return 0;
            }
            ERR_LOG("SOCKET SEND FAILED");
            return -1;
        }
        return n;
    }
    //非阻塞发送数据
    ssize_t NonBlockSend(void* buf, size_t len)
    {
        return send(_sockfd, buf, len, MSG_DONTWAIT);
    }
    //关闭套接字
    void Close()
    {
        if (_sockfd != -1)
            close(_sockfd);
        _sockfd = -1;
    }
    //创建一个服务器连接
    bool CreateServer(uint16_t port, const std::string& ip = "0.0.0.0", bool block_flag = false)
    {
        //创建套接字
        if (Create() == false)
            return false;
        if (block_flag == true)
            NonBlock();
        //设置端口复用
        ReuseAddress();
        //绑定地址
        if (Bind(ip, port) == false)
            return false;
        //开始监听
        if (Listen() == false)
            return false;
        return true;
    }
    //创建一个客户端连接
    bool CreateClient(uint16_t port, const std::string ip)
    {
        //创建套接字
        if (Create() == false)
            return false;
        //连接服务器
        if (Connect(ip, port) == false)
            return false;
        return true;
    }
    /*
        一个连接绑定了地址和端口之后一旦主动关闭连接的一方最终会进入time_wait状态，这时候套接字
        并不会立即被释放，因此IP地址和端口依然被占用，导致我们无法立即去使用它，在服务器使用的时候，
        崩溃了，退出了，会无法立即重启，所以我们要开启地址重用。
    */
    //设置套接字选项 -- 开启端口复用
    void ReuseAddress()
    {
        int opt = 1;
        setsockopt(_sockfd, SOL_SOCKET, SO_REUSEPORT | SO_REUSEADDR, &opt, sizeof(opt));
    }
    /*
        我们在使用套接字去接收数据的时候，一次性可能取不完数据，就需要循环去接收缓冲区里的数据，什么时候取完呢？
        就是取到没有数据为止，但是套接字默认是阻塞的，没有数据的时候再去取就会被阻塞住，程序就
        无法继续往下走了，所以我们需要将套接字设置为非阻塞
    */
    //设置套接字阻塞属性 -- 设置为非阻塞
    void NonBlock()
    {
        int flag = fcntl(_sockfd, F_GETFL, 0);
        fcntl(_sockfd, F_SETFL, flag | O_NONBLOCK);
    }
};


class EventLoop;
class Channel
{
private:
    EventLoop* _loop;
    uint32_t _events;   //当前需要监控的事件
    uint32_t _revents;  //当前连接触发的事件
    using EventCallback = std::function<void()>;
    /*
        只有我们的连接才知道，一旦事件触发了该去怎么处理，所以需要设置回调函数。
        当启动读事件监控，就需要将channel挂到EventLoop上面进行事件监控，
        当可读事件触发，就会调用channel里设置的回调函数。
    */
    EventCallback _read_callback;   //可读事件被触发的回调函数
    EventCallback _write_callback;  //可写事件被触发的回调函数
    EventCallback _error_callback;  //错误事件被触发的回调函数
    EventCallback _close_callback;  //连接断开事件被触发的回调函数
    EventCallback _event_callback;  //任意事件被触发的回调函数
    int _fd;
public:
    Channel(EventLoop* loop, int fd)
    :_loop(loop), _fd(fd), _events(0), _revents(0)
    {}
    int Fd()
    {
        return _fd;
    }
    uint32_t Events()
    {
        return _events;
    }
    void SetREvents(uint32_t events)
    {
        _revents = events;
    }
    void SetReadCallback(const EventCallback& cb)
    {
        _read_callback = cb;
    }
    void SetWriteCallback(const EventCallback& cb)
    {
        _write_callback = cb;
    }
    void SetErrorCallback(const EventCallback& cb)
    {
        _error_callback = cb;
    }
    void SetCloseCallback(const EventCallback& cb)
    {
        _close_callback = cb;
    }
    void SetEventCallback(const EventCallback& cb)
    {
        _event_callback = cb;
    }
    //当前是否监控了可读
    bool ReadAble()
    {
        return (_events & EPOLLIN);
    }
    //当前是否监控了可写
    bool WriteAble()   
    {
        return (_events & EPOLLOUT);
    }
    //启动读事件监控
    void EnableRead()
    {
        _events |= EPOLLIN;
        Update();
    }
    //启动可写事件监控
    void EnableWrite()
    {
        _events |= EPOLLOUT;
        Update();
    }
    //关闭读事件监控
    void DisableRead()
    {
        _events &= ~EPOLLIN;
        Update();
    }
    //关闭写事件监控
    void DisableWrite()
    {
        _events &= ~EPOLLOUT;
        Update();
    }
    //关闭所有事件监控
    void DisableAll()
    {
        _events &= 0;
    }
    /*
        关闭事件监控，只是不去关心这个事件了，但还是在EventLoop中。
        移除事件监控，才是真正的将它从EventLoop中移除
    */
    //移除监控
    void Remove();
    void Update();

    /*
        EventLoop不用 你触发了什么事件我就去调用对应的回调函数，EventLoop不用管。
        EventLoop只管你触发了事件，我就调用你的HandleEvent，你自己来决定什么样的事件该如何处理
        这是最能体现Channel模块作用的功能之一
    */
    void HandleEvent()
    {
        if ((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI))
        {
            if (_event_callback)
                _event_callback();
            if (_read_callback)
                _read_callback();
        }
        //有可能会释放连接的操作事件，一次只处理一个
        if (_revents & EPOLLOUT)
        {
            if (_event_callback)
                _event_callback();
            if (_write_callback)
                _write_callback();
        }
        else if (_revents & EPOLLERR)
        {
            if (_event_callback)
                _event_callback();
            if (_error_callback)
                _error_callback();
        }
        else if (_revents & EPOLLHUP)
        {
            if (_event_callback)
                _event_callback();
            if (_close_callback)
                _close_callback();
        }
    }
};


#define MAX_EPOLLEVENTS 1024
class Poller
{
private:
    int _epfd;
    struct epoll_event _evs[MAX_EPOLLEVENTS];
    std::unordered_map<int, Channel*> _channels;    //这个和epoll里面的所有文件描述符是强绑定的
private:
    //对epoll的直接操作
    void Update(Channel* channel, int op)
    {
        int fd = channel->Fd();
        struct epoll_event ev;
        ev.data.fd = fd;
        ev.events = channel->Events();
        int ret = epoll_ctl(_epfd, op, fd, &ev);
        if (ret < 0)
        {
            ERR_LOG("EPOLLCTL FAILED");
        }
        return;
    }
    //判断一个Channel是否已经添加了事件监控
    bool HasChannel(Channel* channel)
    {
        auto pos = _channels.find(channel->Fd());
        if (pos == _channels.end())
        {
            return false;
        }
        return true;
    }
public:
    Poller()
    {
        _epfd = epoll_create(MAX_EPOLLEVENTS);
        if (_epfd < 0)
        {
            ERR_LOG("EPOLL CREATE TAILED!");
            abort();    //退出程序
        }
    }
    //添加或修改监控事件
    void UpdateEvent(Channel* channel)
    {
        bool ret = HasChannel(channel);
        if (ret == false)
        {
            _channels.insert(std::make_pair(channel->Fd(), channel));
            return Update(channel, EPOLL_CTL_ADD);
        }
        return Update(channel, EPOLL_CTL_MOD);
    }
    //移除监控
    void RemoveEvent(Channel* channel)
    {
        bool ret = HasChannel(channel);
        if (ret == false)
        {
            return;
        }
        _channels.erase(channel->Fd());
        return Update(channel, EPOLL_CTL_DEL);
    }
    //开始监控，返回活跃连接
    void Poll(std::vector<Channel*>* active)
    {
        int n = epoll_wait(_epfd, _evs, MAX_EPOLLEVENTS, -1);
        if (n < 0)
        {
            if (errno == EINTR) //如果被信号打断了
            {
                return;
            }
            ERR_LOG("EPOLL WAIT FAILED:%s", strerror(errno));
            abort();
        }
        for (int i = 0; i < n; ++i)
        {
            auto it = _channels.find(_evs[i].data.fd);
            assert(it != _channels.end());
            it->second->SetREvents(_evs[i].events);
            active->push_back(it->second);
        }
    }
};

using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
class TimerTask
{
private:
    uint64_t _id;   //定时器任务对象ID  定时任务必须得找得着，一个程序里定时任务可能有很多
    uint32_t _timeout;  //定时任务的超时时间
    TaskFunc _task_cb;  //定时器要执行的任务
    //用于删除TimerWheel中保存的定时器任务对象信息，定时任务释放的时候也要清理TimerWheel中保存的定时器对象信息
    //为什么将这个_release设置到TimerTask里面呢，不在TimerWheel层管理？
    //因为这个TimerWheel不知道是否某个定时任务真的释放了，而TimerTask是最清楚的，自己真的释放了就会调用析构函数
    ReleaseFunc _release;
    bool _canceled;     //false - 代表没有被取消，true - 代表取消了
public:
    TimerTask(uint64_t id, uint32_t timeout, const TaskFunc& cb)
    :_id(id), _timeout(timeout), _task_cb(cb), _canceled(false)
    {}
    ~TimerTask()
    {
        if (_canceled == false) //如果定时任务没有被取消
            _task_cb(); 
        _release();
    }
    void SetRelease(const ReleaseFunc& cb)
    {
        _release = cb;
    }
    uint32_t DelayTime()
    {
        return _timeout;
    }
    void Cancel()
    {
        _canceled = true;
    }
};

class TimerWheel
{
private:
    using WeakTask = std::weak_ptr<TimerTask>;
    using PtrTask = std::shared_ptr<TimerTask>;
    int _tick;      //当前的秒针，走到哪里释放哪里，就相当于执行哪里的任务
    int _capacity;  //表盘最大数量 -- 也是最大能设置的延时时间
    std::vector<std::vector<PtrTask>> _wheel;
    std::unordered_map<uint64_t, WeakTask> _timers;     //对所有的定时任务进行管理

    EventLoop* _loop;   //timerwheel所关联的EventLoop
    int _timerfd;       //定时器描述符
    std::unique_ptr<Channel> _timer_channel;
public:
    void RemoveTimer(uint64_t id)
    {
        auto pos = _timers.find(id);
        if (pos != _timers.end())
        {
            _timers.erase(pos);
        }
    }
    static int CreateTimerFd()
    {
        int timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
        if (timerfd < 0)
        {
            ERR_LOG("TIMERFD CREATE FAILED");
            abort();
        }
        struct itimerspec itime;
        itime.it_value.tv_sec = 1;
        itime.it_value.tv_nsec = 0;
        itime.it_interval.tv_sec = 1;
        itime.it_interval.tv_nsec = 0;

        timerfd_settime(timerfd, 0, &itime, NULL);
        return timerfd;
    }
    int ReadTimefd()
    {
        uint64_t times;
        int ret = read(_timerfd, &times, 8);
        if (ret < 0)
        {
            ERR_LOG("READ TIMEFD FAILED");
            abort();
        }
        return times;
    }
    void RunTimerTask()
    {
        _tick = (_tick + 1) % _capacity;
        _wheel[_tick].clear();  //情况指定位置的数组，就会把数组中保存的所有管理定时器对象的shared_ptr释放掉
    }
    //这个函数每秒钟会被执行一次，相当于秒针向后走了一步
    void OnTime()
    {
        int times = ReadTimefd();
        for (int i = 0; i < times; ++i)
            RunTimerTask();
    }
    void TimerAddInLoop(uint64_t id, uint32_t delay, const TaskFunc& cb)
    {
        //1.构建定时任务
        PtrTask pt(new TimerTask(id, delay, cb));
        pt->SetRelease(std::bind(&TimerWheel::RemoveTimer, this, id));
        //2.将定时任务加入到_wheel中
        int i = (_tick + delay) % _capacity;
        _wheel[i].push_back(pt);
        //3.加入到时间轮的_timers里面
        // std::unordered_map<uint64_t, WeakTask>::iterator pos = _timers.find(id);
        auto pos = _timers.find(id);
        if (pos == _timers.end())
        {
            _timers.insert({id, pt});
        }
    }
    void TimerRefreshInLoop(uint64_t id)  //刷新/延迟定时任务
    {
        //通过id找到对应的定时任务
        auto pos = _timers.find(id);
        if (pos == _timers.end())
        {
            //如果没找到定时任务，则没办法更新
            return;
        }
        //获取到对应定时任务的shared_ptr，并构建一个新的智能指针，对应的计数加1
        PtrTask pt = pos->second.lock();
        //将对应的pt加入到_wheel中
        int delay = pt->DelayTime();
        int i = (_tick + delay) % _capacity;
        _wheel[i].push_back(pt);
    }
    void TimerCancelInLoop(uint64_t id)
    {
        auto pos = _timers.find(id);
        if (pos == _timers.end())
        {
            //没找到定时任务，没法刷新，没法延时
            return;
        }
        PtrTask pt = pos->second.lock();
        if (pt) //如果自己已经销毁，则可能为空
            pt->Cancel();
    }
public:
    TimerWheel(EventLoop* loop)
    :_capacity(60)
    , _tick(0)
    , _wheel(_capacity)
    , _loop(loop)
    , _timerfd(CreateTimerFd())
    , _timer_channel(new Channel(loop, _timerfd))
    {
        _timer_channel->SetReadCallback(std::bind(&TimerWheel::OnTime, this));
        _timer_channel->EnableRead();
    }
    //定时器中有个_timers成员，定时器信息的操作有可能在多线程中进行(如主线程想添加给所有的连接添加一个定时任务)，因此需要考虑线程安全问题
    //如果不想加锁，那就把对应定期的所有操作，都放到一个线程中进行
    void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc& cb); //因为用到了EventLoop的_loop成员，所以要在EventLoop代码后面去实现
    void TimerRefresh(uint64_t id);
    void TimerCancel(uint64_t id);

    //这个接口存在线程安全问题--这个接口不能被外界使用者调用，只能在模块内，在对应的EventLoop线程内执行
    bool HasTimer(uint64_t id)
    {
        auto it = _timers.find(id);
        if (it == _timers.end())
        {
            return false;
        }
        return true;
    }
};

class EventLoop
{
private:
    std::thread::id _thread_id; //线程ID
    int _event_fd;  //唤醒阻塞的IO事件监控
    std::unique_ptr<Channel> _event_channel;    //为了能更好的管理_event_fd，为其创建一个channel
    Poller _poller; //进行所有的描述符的事件监控

    using Functor = std::function<void()>;
    std::vector<Functor> _tasks;    //任务池
    std::mutex _mutex;     //保证多线程对任务池进行操作的线程安全
    TimerWheel _timer_wheel;
public:
    //执行任务池中的所有任务
    void RunAllTask()
    {
        std::vector<Functor> functor;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            functor.swap(_tasks);
        }
        for (auto f : functor)
        {
            if (f)
            f();
        }
    }
    static int CreateEventFd()
    {
        int efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
        if (efd < 0)
        {
            perror("eventfd failed");
            abort();
        }
        return efd;
    }
    void ReadEvent()
    {
        uint64_t res = 0;
        int ret = read(_event_fd, &res, sizeof(res));
        if (ret < 0)
        {
            //EINTR -- 被信号打断    EAGAIN -- 暂时无数据可读（非阻塞时才会触发）
            if (errno == EINTR || errno == EAGAIN)
            {
                return;
            }
            ERR_LOG("READ EVENTED FAILED");
            abort();
        }
    }
    void WeakUpEventFd()
    {
        uint64_t val = 1;
        int ret = write(_event_fd, &val, sizeof(val));
        if (ret < 0)
        {
            if (errno == EINTR)
            {
                return;
            }
            ERR_LOG("WRITE EVENTFD FAILED");
            abort();
        }
    }
public:
    EventLoop()
    :_thread_id(std::this_thread::get_id()) //获取的是当前实例化该EventLoop线程的id，进行线程绑定
    ,_event_fd(CreateEventFd())
    ,_event_channel(new Channel(this, _event_fd))
    ,_timer_wheel(this)
    {
        //给eventfd添加可读事件回调，读取eventfd事件通知次数
        _event_channel->SetReadCallback(std::bind(&EventLoop::ReadEvent, this));
        //启动eventfd的读事件监控
        _event_channel->EnableRead();
    }
    //判断将要执行的任务是否处于当前线程中，如果是则执行，不是则压入队列
    void RunInLoop(const Functor& cb)
    {
        if (IsInLoop())
        {
            return cb();
        }
        return QueueInLoop(cb);
    }
    //将操作压入任务池
    void QueueInLoop(const Functor& cb)
    {
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _tasks.push_back(cb);
        }
        //其他线程把任务投入到你的EventLoop的任务池里面了，需要执行任务池里的这个任务
        //所以需要唤醒这个线程（因为这个线程可能在等待事件就绪的阻塞状态）
        WeakUpEventFd();
    }
    //用于判断当前线程是否是EventLoop对应的线程
    bool IsInLoop()
    {
        return _thread_id == std::this_thread::get_id();
    }
    //添加/修改描述符的事件监控
    void UpdateEvent(Channel* channel)
    {
        _poller.UpdateEvent(channel);
    }
    //移除描述符的监控
    void RemoveEvent(Channel* channel)
    {
        _poller.RemoveEvent(channel);
    }
    void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc& cb)
    {
        return _timer_wheel.TimerAdd(id, delay, cb);
    }
    void TimerRefresh(uint64_t id)
    {
        return _timer_wheel.TimerRefresh(id);
    }
    void TimerCancel(uint64_t id)
    {
        return _timer_wheel.TimerCancel(id);
    }
    bool HasTimer(uint64_t id)
    {
        return _timer_wheel.HasTimer(id);
    }
    void Start()
    {
        while (1)
        {
            //事件监控
            std::vector<Channel*> actives;
            _poller.Poll(&actives);
            //就绪事件处理
            for (auto& channel : actives)
            {
                channel->HandleEvent();
            }
            //执行任务池中的任务
            RunAllTask();
        }
    }
};

class LoopThread
{
private:
    //主要是为了实现同步，避免新线程还没来得及实例化_loop的时候，主线程就要获取对应的EventLoop
    std::mutex _mutex;          //互斥锁
    std::condition_variable _cond;  //条件变量
    EventLoop* _loop;
    std::thread _thread;        //EventLoop对应的线程
private:
    //实例化EventLoop对象，并且开始运行EventLoop模块的功能
    void ThreadEntry()
    {
        EventLoop loop; //因为下面Start会一直循环运行，所以EventLoop的生命周期不会结束
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _loop = &loop;
            _cond.notify_all();
        }
        loop.Start();
    }
public:
    LoopThread()
    :_loop(NULL)
    ,_thread(std::thread(&LoopThread::ThreadEntry, this))//创建线程，设定线程入口函数
    {}
    //返回当前线程关联的EventLoop对象指针
    EventLoop* GetLoop()
    {
        EventLoop* loop = NULL;
        {
            std::unique_lock<std::mutex> lock(_mutex);  //加锁
            //第二个参数时一个bool的函数，如果为false就一直阻塞住，被唤醒才能继续往下走
            _cond.wait(lock, [&](){
                return _loop != nullptr;
            });
            loop = _loop;
        }
        return loop;
    }
};

class LoopThreadPool
{
private:
    int _thread_count;  //从属线程的数量
    int _next_idx;
    EventLoop* _baseLoop;   //主EventLoop，运行在主线程，从属线程数量为0，则所有操作都在baseloop中进行
    std::vector<LoopThread*> _threads;  //保存所有的LoopThread对象
    std::vector<EventLoop*> _loops;     //从属线程数量大于0则从_loops中进行线程EventLoop分配
public:
    LoopThreadPool(EventLoop* baseLoop)
    :_thread_count(0)
    ,_next_idx(0)
    ,_baseLoop(baseLoop)
    {}
    //设置线程数量
    void SetThreadCount(int count)
    {
        _thread_count = count;
    }
    //创建所有的从属线程
    void Create()
    {
        if (_thread_count > 0)
        {
            _threads.resize(_thread_count);
            _loops.resize(_thread_count);
            for (int i = 0; i < _thread_count; ++i)
            {
                _threads[i] = new LoopThread;
                _loops[i] = _threads[i]->GetLoop();
            }
        }
    }
    //为了实现RR轮转，返回下一个从属线程的EventLoop
    EventLoop* NextLoop()
    {
        if (_thread_count == 0)
        {
            return _baseLoop;
        }
        _next_idx = (_next_idx + 1) % _thread_count;
        return _loops[_next_idx];
    }
};


class Any
{
public:
    class holder
    {
    public:
        virtual ~holder()
        {}
        virtual const std::type_info& type() = 0;  //获取当前子类的数据类型 -- 返回类型是const type_info&
        virtual holder* clone() = 0;        //针对当前的对象自身，克隆出一个新的子类对象
    };

    template<class T>
    class placeholder : public holder
    {
    public:
        placeholder(const T& val = T()):_val(val)
        {}
        virtual const std::type_info& type()
        {
            return typeid(T);
        }
        virtual holder* clone()
        {
            return new placeholder(_val);
        }
        T _val;     //主要是这里，如果不通过virtual，则无法释放这里的对象
    };

    Any():_content(NULL)
    {}
    template <class T>
    Any(const T& content):_content(new placeholder<T>(content))
    {}
    Any(const Any& other)
    :_content(other._content ? other._content->clone() : NULL)
    {}
    ~Any()
    {
        delete _content;
    }
    Any& swap(Any& other)
    {
        std::swap(_content, other._content);
        return *this;
    }
    template<class T>
    Any& operator=(const T& val)
    {
        Any(val).swap(*this);   //这样写的好处：Any(val)为临时对象，交换完生命周期就到了，就会调用自己的析构函数
        return *this;
    }
    Any& operator=(const Any& other)
    {
        Any(other).swap(*this);
        return *this;
    }

    template<class T>
    T* get()    //返回子类对象保存数据的指针
    {
        if (typeid(T) != _content->type())  //如果你要的类型和我保存的类型不匹配
            return NULL;
        return &(((placeholder<T>*)_content)->_val);
    }
public:
    holder* _content;
};

typedef enum
{
    DISCONNECTED,   //连接关闭状态
    CONNECTING,     //连接建立成功 - 待处理状态
    CONNECTED,      //连接建立完成，各种设置已完成，可以通信的状态
    DISCONNECTING   //待关闭状态
}ConnStatu;

class Connection;
using PtrConnection = std::shared_ptr<Connection>;

class Connection : public std::enable_shared_from_this<Connection>
{
private:
    uint64_t _conn_id;  //连接的唯一ID，也是定时任务唯一ID，便于连接的管理和查找
    int _sockfd;        //连接关联的文件描述符
    bool _enable_inactive_release;  //连接是否启动非活跃销毁的判断标志，默认为false
    EventLoop* _loop;   //连接所关联的一个EventLoop
    ConnStatu _statu;   //连接状态
    Socket _socket;     //套接字操作管理
    Channel _channel;   //连接的事件管理
    Buffer _in_buffer;  //输入缓冲区 -- 存放从socket中读取到的数据
    Buffer _out_buffer; //输出缓冲区 -- 存放要发送给对端的数据
    Any _context;       //请求的接收处理上下文

    //以下这四个回调函数吗，是让Server模块来设置的(服务器模块的处理回调是组件使用者设置的)
    using ConnectedCallback = std::function<void(const PtrConnection&)>;
    using MessageCallback = std::function<void(const PtrConnection&, Buffer*)>;
    using ClosedCallback = std::function<void(const PtrConnection&)>;
    using AnyEventCallback = std::function<void(const PtrConnection&)>;
    ConnectedCallback _connected_callback;
    MessageCallback _message_callback;
    ClosedCallback _closed_callback;
    AnyEventCallback _event_callback;
    //组件内的连接关闭回调 -- 组件内设置的，因为服务器组件内会把所有的连接管理起来。
    //一旦某个连接要关闭，就应该从管理的地方移除掉自己的信息。
    ClosedCallback _server_closed_callback;
private:
    //五个channel的事件回调函数
    //描述符可读事件触发后调用的函数，接收socket数据放到接收缓冲区中，然后调用_message_callback
    void HandleRead()
    {
        char buf[65536];
        ssize_t ret = _socket.NonBlockRecv(buf, 65535);
        if (ret < 0)
        {
            //读出错了，可能是客户端关闭，不能直接关闭连接，因为可能有数据没发送或者有数据还没处理
            return ShutdownInLoop();
        }
        else if (ret == 0)
        {
            //表示没有读取到数据，并不是连接断开，因为我们调用的是自己封装的NonBlockRecv
            return;
        }
        _in_buffer.WriteAndPush(buf, ret);
        //2.调用message_callback进行业务处理
        if (_in_buffer.ReadAbleSize() > 0)
        {
            //shared_from_this -- 从当前对象自身获取自身的shared_ptr管理对象
            _message_callback(shared_from_this(), &_in_buffer);
        }
    }
    //描述符可写事件触发后调用的函数，将发送缓冲区中的数据进行发送
    void HandleWrite()
    {
        ssize_t ret = _socket.NonBlockSend(_out_buffer.ReadPosition(), _out_buffer.ReadAbleSize());
        if (ret < 0)
        {
            if (_in_buffer.ReadAbleSize() > 0)
            {
                _message_callback(shared_from_this(), &_in_buffer);
            }
            return Release(); //实际的关闭释放操作
        }
        _out_buffer.MoveReadOffset(ret);    //千万不要忘了，将读偏移向后移动
        if (_out_buffer.ReadAbleSize() == 0)
        {
            _channel.DisableWrite();    //如果数据发送完了，就关闭写事件监控
            //如果当前是连接待关闭状态，并且数据发送完毕，则可以将连接直接释放
            if (_statu == DISCONNECTING)
            {
                return Release();
            }
        }
        //发送数据可能发不完，不关闭写事件监控
        return;
    }
    //描述符触发挂断事件
    void HandleClose()
    {
        if (_in_buffer.ReadAbleSize() > 0)
        {
            _message_callback(shared_from_this(), &_in_buffer);
        }
        return Release();
    }
    //描述符触发出错事件
    void HandleError()
    {
        return HandleClose();
    }
    //描述符触发任意事件
    void HandleEvent()
    {
        //刷新连接活跃度
        if (_enable_inactive_release == true)
        {
            _loop->TimerRefresh(_conn_id);
        }
        //调用组件使用者的任意事件回调
        if (_event_callback)
            _event_callback(shared_from_this());
    }
    //连接获取之后，所处的状态下要进行各种设置
    void EstablishedInLoop()
    {
        //修改连接状态
        assert(_statu == CONNECTING);
        _statu = CONNECTED;
        _channel.EnableRead();
        if (_connected_callback)
            _connected_callback(shared_from_this());
    }
    //这个接口才是实际的释放接口
    void ReleaseInLoop()
    {
        //修改连接状态，将其置为DISCONNECTED
        _statu = DISCONNECTED;
        //移除连接的事件监控
        _channel.Remove();
        //关闭描述符
        _socket.Close();
        //如果当前定时器队列中还有定时任务，则取消任务
        if (_loop->HasTimer(_conn_id))
            CancelInactiveRelease();
        //调用关闭回调函数，避免先移除服务器管理的连接信息导致Connection被释放，因此先调用户的回调函数
        if (_closed_callback)
            _closed_callback(shared_from_this());
        if (_server_closed_callback)
            _server_closed_callback(shared_from_this());
    }
    //这个接口并不是实际的发送接口，而只是把数据放到了发送缓冲区，启动了可写事件监控
    //为什么要这么做？因为可写条件可能不就绪，即内核缓冲区的数据满了，写不进去了
    void SendInLoop(Buffer buf)
    {
        if (_statu == DISCONNECTED) //如果状态已经关闭，则直接return，已经关闭则代表发送缓冲区数据为0
            return;
        _out_buffer.WriteBufferAndPush(buf);
        if (_channel.WriteAble() == false)
            _channel.EnableWrite();
    }
    //这个关闭操作并非实际的连接释放操作，需要判断还有没有数据待处理，待发送
    void ShutdownInLoop()
    {
        _statu = DISCONNECTING; //设置为半关闭状态
        if (_in_buffer.ReadAbleSize() > 0)
            _message_callback(shared_from_this(), &_in_buffer);
        if (_out_buffer.ReadAbleSize() > 0)
            _channel.EnableWrite();
        //因为可能发送缓冲区将数据发送不完，所以写关心就不用关闭了，也不用真正释放了
        if (_out_buffer.ReadAbleSize() == 0)
        {
            _channel.DisableWrite();
            Release();
        }
    }
    //启动非活跃连接超时释放规则
    void EnableInactiveReleaseInLoop(int sec)
    {
        //将判断标志 _enable_inactive_erlease置为true
        _enable_inactive_release = true;
        //如果当前定时销毁任务已经存在，那就刷新延迟一下即可
        if (_loop->HasTimer(_conn_id))
            return _loop->TimerRefresh(_conn_id);
        //如果不存在定时销毁任务，则新增
        _loop->TimerAdd(_conn_id, sec, std::bind(&Connection::Release, this));
    }
    //取消非活跃连接超时释放规则
    void CancelInactiveReleaseInLoop()
    {
        _enable_inactive_release = false;
        if (_loop->HasTimer(_conn_id))
            _loop->TimerCancel(_conn_id);
    }
    //切换/升级协议
    void UpgradeInLoop(const Any& context, const ConnectedCallback& conn, const MessageCallback& msg, const ClosedCallback& closed, const AnyEventCallback& event)
    {
        _context = context; //改变上下文
        _connected_callback = conn;
        _message_callback = msg;
        _closed_callback = closed;
        _event_callback = event;
    }
public:
    Connection(EventLoop* loop, uint64_t conn_id, int sockfd)
    :_conn_id(conn_id)
    ,_sockfd(sockfd)
    ,_enable_inactive_release(false)
    ,_loop(loop)
    ,_statu(CONNECTING)
    ,_socket(sockfd)
    ,_channel(loop, _sockfd)
    {
        _channel.SetReadCallback(std::bind(&Connection::HandleRead, this));
        _channel.SetWriteCallback(std::bind(&Connection::HandleWrite, this));
        _channel.SetCloseCallback(std::bind(&Connection::HandleClose, this));
        _channel.SetErrorCallback(std::bind(&Connection::HandleError, this));
        _channel.SetEventCallback(std::bind(&Connection::HandleEvent, this));
    }
    ~Connection()
    {
        DBG_LOG("RELEASE CONNEDCTION: %p", this);
    }
    //获取管理的文件描述符
    int Fd()
    {
        return _sockfd;
    }
    //获取连接ID
    int Id()
    {
        return _conn_id;
    }
    //是否处于CONNECTED状态
    bool Connected()
    {
        return (_statu == CONNECTED);
    }
    //设置上下文 -- 连接建立完成时进行调用
    void SetContext(const Any& context)
    {
        _context = context;
    }
    //获取上下文，返回的是指针
    Any* GetContext()
    {
        return &_context;
    }
    void SetConnectedCallback(const ConnectedCallback& cb)
    {
        _connected_callback = cb;
    }
    void SetMessageCallback(const MessageCallback& cb)
    {
        _message_callback = cb;
    }
    void SetClosedCallback(const ClosedCallback& cb)
    {
        _closed_callback = cb;
    }
    void SetSvrClosedCallback(const ClosedCallback& cb)
    {
        _server_closed_callback = cb;
    }
    void SetAnyEventCallback(const AnyEventCallback& cb)
    {
        _event_callback = cb;
    }
    //连接建立就绪后，进行channel回调设置，启动读监控，调用_connected_callback
    void Establised()
    {
        _loop->RunInLoop(std::bind(&Connection::EstablishedInLoop, this));
    }
    //发送数据，将数据放到发送缓冲区，启动写事件监控
    void Send(const char* data, size_t len)
    {
        Buffer buf; //为什么要重新创建一个临时变量？因为data可能是一个可能被释放的空间，我们将其压入任务队列等待被执行的过程中，空间可能被释放了
        buf.WriteAndPush(data, len);
        _loop->RunInLoop(std::bind(&Connection::SendInLoop, this, std::move(buf)));
    }
    //提供给组件使用者的关闭接口 -- 并不实际关闭，需要判断有没有数据待处理
    void Shutdown()
    {
        _loop->RunInLoop(std::bind(&Connection::ShutdownInLoop, this));
    }
    void Release()
    {
        _loop->QueueInLoop(std::bind(&Connection::ReleaseInLoop, this));
    }
    //启动非活跃销毁，并定义多长时间无通信就是非活跃，添加定时任务
    void EnableInactiveRelease(int sec)
    {
        _loop->RunInLoop(std::bind(&Connection::EnableInactiveReleaseInLoop, this, sec));
    }
    //取消非活跃销毁
    void CancelInactiveRelease()
    {
        _loop->RunInLoop(std::bind(&Connection::CancelInactiveReleaseInLoop, this));
    }
    //切换协议 -- 重置上下文以及阶段性处理函数
    void Upgrade(const Any& context, const ConnectedCallback& conn, const MessageCallback& msg, const ClosedCallback& closed, const AnyEventCallback& event)
    {
        _loop->RunInLoop(std::bind(&Connection::UpgradeInLoop, this, context, conn, msg, closed, event));
    }
};

class Acceptor
{
private:
    Socket _socket;     //用于创建监听套接字
    EventLoop* _loop;   //用于对监听套接字进行事件监控
    Channel _channel;   //对于对监听套接字进行事件管理

    using AcceptCallback = std::function<void(int)>;
    AcceptCallback _accept_callback;    //由Server模块提供的回调函数
private:
    //监听套接字的读事件回调处理函数 -- 获取新连接，调用_accept_callback函数进行新连接处理
void HandleRead()
{
    int newfd = _socket.Accept();
    if (newfd < 0)
        return;
    if (_accept_callback)
        _accept_callback(newfd);
}
    int CreateServer(uint16_t port)
    {
        bool ret = _socket.CreateServer(port);
        if (ret < 0)
            abort();
        return _socket.Fd();
    }
public:
    Acceptor(EventLoop* loop, int port)
    :_loop(loop)
    ,_socket(CreateServer(port))
    ,_channel(loop, _socket.Fd())
    {
        _channel.SetReadCallback(std::bind(&Acceptor::HandleRead, this));
    }
    void SetAcceptCallback(const AcceptCallback& cb)
    {
        _accept_callback = cb;
    }
    void Listen()
    {
        _channel.EnableRead();//启动监听的可读事件监控 -- 会自动将自己挂到poller中
    }
};

class TcpServer
{
private:
    uint16_t _port;
    uint64_t _next_id;  //这是Connection和定时任务公用的id
    int _timeout;       //非活跃连接的超时时间
    bool _enable_inactive_release;  //是否启动了非活跃连接超时销毁的判断标志
    EventLoop _baseloop;    //主线程EventLoop对象，负责 监听事件的处理
    Acceptor _acceptor;     //监听套接字的管理对象
    LoopThreadPool _pool;   //这是从属EventLoop线程池
    std::unordered_map<uint64_t, PtrConnection> _conns; //保存管理所有连接对应的shared_ptr对象 -- 这里面的东西被删除，就意味着这个连接在某个不久的将来会被释放

    //用户设置的回调函数 -- 未来要设置给Connection
    using ConnectedCallback = std::function<void(const PtrConnection&)>;
    using MessageCallback = std::function<void(const PtrConnection&, Buffer*)>;
    using ClosedCallback = std::function<void(const PtrConnection&)>;
    using AnyEventCallback = std::function<void(const PtrConnection&)>;
    using Functor = std::function<void()>;
    ConnectedCallback _connected_callback;
    MessageCallback _message_callback;
    ClosedCallback _closed_callback;
    AnyEventCallback _event_callback;
private:
    //为新连接构造一个Connection
    void NewConnection(int fd)
    {
        _next_id++;
        PtrConnection conn(new Connection(_pool.NextLoop(), _next_id, fd));
        conn->SetMessageCallback(_message_callback);
        conn->SetClosedCallback(_closed_callback);
        conn->SetSvrClosedCallback(std::bind(&TcpServer::RemoveConnection, this, std::placeholders::_1));
        conn->SetConnectedCallback(_connected_callback);
        conn->SetAnyEventCallback(_event_callback);
        if (_enable_inactive_release == true)
            conn->EnableInactiveRelease(_timeout);    //启动非活跃超时销毁
        conn->Establised(); //就绪初始化
        _conns.insert(std::make_pair(_next_id, conn));
        DBG_LOG("获取到了一个新的连接");
    }
    void RemoveConnectionInLoop(const PtrConnection& conn)
    {
        int id = conn->Id();
        auto it = _conns.find(id);
        if (it != _conns.end())
        {
            _conns.erase(it);
        }
    }
    //从管理Connection的_conns中移除连接信息 -- 因为对STL容器进行操作，所以需要考虑线程安全问题
    void RemoveConnection(const PtrConnection& conn)
    {
        _baseloop.RunInLoop(std::bind(&TcpServer::RemoveConnectionInLoop, this, conn));
    }
    void RunAfterInLoop(const Functor& task, int delay)
    {
        _next_id++;
        _baseloop.TimerAdd(_next_id, delay, task);
    }
public:
    TcpServer(int port)
    :_port(port), _next_id(0), _enable_inactive_release(false), _acceptor(&_baseloop, port)
    ,_pool(&_baseloop)
    {
        _acceptor.SetAcceptCallback(std::bind(&TcpServer::NewConnection, this, std::placeholders::_1));
        _acceptor.Listen();
    }
    //设置从属线程数量
    void SetThreadCount(int count)
    {
        return _pool.SetThreadCount(count);
    }
    void SetConnectedCallback(const ConnectedCallback& cb)
    {
        _connected_callback = cb;
    }
    void SetMessageCallback(const MessageCallback& cb)
    {
        _message_callback = cb;
    }
    void SetClosedCallback(const ClosedCallback& cb)
    {
        _closed_callback = cb;
    }
    void SetAnyEventCallback(const AnyEventCallback& cb)
    {
        _event_callback = cb;
    }
    void EnableInactiveRelease(int timeout)
    {
        _timeout = timeout;
        _enable_inactive_release = true;
    }
    //用于添加一个定时任务 -- 提供给我们用户的
    void RunAfter(const Functor& task, int delay)
    {
        _baseloop.RunInLoop(std::bind(&TcpServer::RunAfterInLoop, this, task, delay));
    }
    void Start()
    {
        _pool.Create();
        _baseloop.Start();
    }
};

void TimerWheel::TimerAdd(uint64_t id, uint32_t delay, const TaskFunc& cb)
{
    _loop->RunInLoop(std::bind(&TimerWheel::TimerAddInLoop, this, id, delay, cb));
}
void TimerWheel::TimerRefresh(uint64_t id)
{
    _loop->RunInLoop(std::bind(&TimerWheel::TimerRefreshInLoop, this, id));
}
void TimerWheel::TimerCancel(uint64_t id)
{
    _loop->RunInLoop(std::bind(&TimerWheel::TimerCancelInLoop, this, id));
}

void Channel::Remove()
{
    return _loop->RemoveEvent(this);
}

void Channel::Update()
{
    return _loop->UpdateEvent(this);
}

class NetWork
{
public:
    NetWork()
    {
        // DBG_LOG("SIGPIPE INIT");
        signal(SIGPIPE, SIG_IGN);
    }
};
static NetWork nw;  //主要是调用该类的构造函数
